package com.lagou.tomcat.container;
import com.lagou.tomcat.parser.ServerXmlParser;
import com.lagou.tomcat.request.RequestProcessor;

import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;

/**
 * @author zhangjinshan
 * @version 1.0
 * @description
 * @date 2021/7/15 上午8:02
 */
public class Server {

    List<Service> services = new ArrayList<>();

    private ThreadPoolExecutor threadPoolExecutor;

    public void init(){
        InputStream resourceAsStream = this.getClass().getClassLoader().getResourceAsStream("server.xml");
        ServerXmlParser serverXmlParser = new ServerXmlParser(resourceAsStream);
        serverXmlParser.parse(services);
    }

    public void start(){
        this.initThreadPool();
        for (Service service : services) {
            List<Connector> connectors = service.getConnectors();
            for (Connector connector : connectors) {
                try {
                    ServerSocket serverSocket = new ServerSocket(connector.getPort());
                    System.out.println("=======>>>> mini-tomcat start on port: " + connector.getPort());
                    while (true) {
                        Socket socket = serverSocket.accept();
                        RequestProcessor requestProcessor = new RequestProcessor(socket, service.getEngine().getMapper());
                        threadPoolExecutor.execute(requestProcessor);
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 初始化线程池
     */
    private void initThreadPool() {
        int corePoolSize = 10;
        int maximumPoolSize = 50;
        long keepAliveTime = 100L;
        TimeUnit unit = TimeUnit.SECONDS;
        BlockingQueue<Runnable> workQueue = new ArrayBlockingQueue<>(50);
        ThreadFactory threadFactory = Executors.defaultThreadFactory();
        RejectedExecutionHandler handler = new ThreadPoolExecutor.AbortPolicy();

        threadPoolExecutor = new ThreadPoolExecutor(
                corePoolSize,
                maximumPoolSize,
                keepAliveTime,
                unit,
                workQueue,
                threadFactory,
                handler);
    }
}
